package basic.concurrent;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;

/**
 * Fork/join 分割/聚合
 * 对大任务进行分割 对结果聚合
 * USER: lintc 【lintiancong@zhuojianchina.com】
 * DATE: 2017-05-27 09:48
 */
public class CountDoubleForkTask extends RecursiveTask<Double> {

    // 阀值
    private static final int THRESHOULD = 10000;

    private int start;

    private int end;

    public CountDoubleForkTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Double compute() {
        Double sum = new Double(0);

        // 如果任务足够小就计算任务
        boolean canCompute = (end - start) <= THRESHOULD;
        if (canCompute) {
            for (int i = start; i <= end; i++) {
                sum += i;
//                System.out.println(i + ":" + sum);
            }
            System.out.println(start + "+" + end + ":" + sum);
//            sum = (BigInteger.valueOf(start).add(BigInteger.valueOf(end)))
//                    .multiply((BigInteger.valueOf(end).subtract(BigInteger.valueOf(start))))
//                    .divide(BigInteger.valueOf(2));
//            System.out.println(sum);
        } else {
            // 分割任务
            int middle = (start + end) / 2;
            CountDoubleForkTask left = new CountDoubleForkTask(start, middle);
            CountDoubleForkTask right = new CountDoubleForkTask(middle + 1, end);
            // 执行子任务
            left.fork();
            right.fork();

            Double left1 = left.join();
            Double right1 = right.join();

            sum = left1 + right1;
        }
        return sum;
    }

    public static void main(String[] args) {
//        System.out.println((9931642 + 9941407) * (9941407 - 9931642) / 2);
//        System.out.println((1+4)/2);
//        System.out.println(9941407 - 9931642);
//        System.out.println((9931642 + 9941407));
        long start = System.currentTimeMillis();
        ForkJoinPool pool = new ForkJoinPool();
        CountDoubleForkTask task = new CountDoubleForkTask(1, 1000000000);
        Future<Double> result = pool.submit(task);
        try {
            System.out.println(result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis() - start);
//        System.out.println(BigInteger.valueOf(1).add(BigInteger.valueOf(2)));
    }
}
